#include "MyConnection.h"

using namespace std;

MyConnection::MyConnection():now_conn_size(0),free_conn_size(0)
{
    
}

MyConnection& MyConnection::get_instance()
{
    static MyConnection connpool;
    return connpool;
}


void MyConnection::init(std::string  ip,int port,std::string  usrname,std::string  password,std::string  dbname,int connmaxsize)
{
    m_ip = ip;
    m_port = port;
    m_usrname = usrname;
    m_password = password;
    m_dbname = dbname;
    //max_conn_size = connmaxsize;
 
    for(int i = 0;i < connmaxsize;i++){
        MYSQL * singleconn = NULL;
        singleconn =  mysql_init(singleconn);
        if(singleconn==NULL) 
        {
            // LOG TODO : MYSQL ERROR;
            exit(1);
        }        
        singleconn = mysql_real_connect(singleconn,ip.c_str(),usrname.c_str(),password.c_str(),dbname.c_str(),port,NULL,0);

        if(singleconn==NULL)
        {
            //LOG TODO:
            exit(1);
        }

        sql_pool.push_back(singleconn);
        free_conn_size++;
        
    }

    max_conn_size = free_conn_size;
    //用信号量表示可用连接数
    
    conn_sem = sem(free_conn_size);
}



void  MyConnection::destroy()
{
    locker.lock();
    list<MYSQL *> iter;
    for(iter = sql_pool.begin();iter!=sql_pool.end();iter++)
    {
        auto temp_conn = *iter;
        mysql_close(temp_conn);
    }
    free_conn_size = 0;
    now_conn_size = 0;
    sql_pool.clear();
    locker.unlock();

}


MYSQL * MyConnection::getConn()
{
    MYSQL * conn;
    if(sql_pool.size()==0) return nullptr;
    conn_sem.wait();

    //等待可以取连接的时机

    locker.lock();

    conn = sql_pool.front();
    sql_pool.pop_front();

    free_conn_size--;
    now_conn_size++;

    lock.unlock();

    return conn;
}


bool MyConnection::releaseConn(MYSQL * conn)
{
    if(now_conn_size == 0||conn==nullptr) return false;
    lock.lock();


    sql_pool.push_back(conn);
    now_conn_size--;
    free_conn_size++;
    lock.unlock();
    conn_sem.post();
    //加锁和互斥量的操作要和上面相反
    return true;
}


